
#include "StdAfx.h"
#include "DBQueryQ.h"
#include <Thread.h>
#include <LogService.h>

DBQueryQ::DBQueryQ(){
	worker_ = 0;
	work_obj_ = 0;
	query_fail_reload_ = false;
	name_ = "";
}

DBQueryQ::~DBQueryQ(){
	stop();	
}

bool DBQueryQ::initialize( WorkListener* worker, Work* work_obj, \
			  bool query_fail_reload, char* name, size_t warn_max_que )
{
	name_ = name;
	worker_ = worker;
	work_obj_ = work_obj;
	query_fail_reload_ = query_fail_reload;

	warn_que_size_ = warn_max_que;

	return start( 0, this );
}

size_t DBQueryQ::add_query( const char* buffer, size_t size ){
	BlanketLock lock( &lock_ );
	
	QueryObj* query = getBuffer();
	memset( query, 0, sizeof( QueryObj ) );
	memcpy( query->buffer_, buffer, size );
	
	q_.push( query );
	return q_.producer_size();
}

DBQueryQ::QueryObj* DBQueryQ::getBuffer(){
	BlanketLock lock( &buffer_lock_ );		

	return instances_.alloc();
}

void DBQueryQ::freeBuffer( QueryObj* buffer ){
	BlanketLock lock( &buffer_lock_ );		

	instances_.free( buffer );
}	

DEF_THREAD_RETURN DBQueryQ::run(){	
	LOG_INSTANCE( LOG_SERVICE( "instance" )->Log("db query thread start %s = %u" \
			, __FILE__, getThreadID()) );
	int debug_count = 0;

	QueryObj* obj = 0;

	while( isActive() ){
		while( q_.consumer_size() ){		
			obj = q_.pop();
			
			if(! obj )
				continue;			

			if(! worker_->workPerformed( work_obj_, (void*)&(obj->buffer_) ) ){
				freeBuffer( obj );
				continue;
			}

			if(! query_fail_reload_ )
				continue;

			lock_.Enter();
			q_.push( obj );
			lock_.Exit();

			if( q_.consumer_size() > warn_que_size_ ){
				LOG_INSTANCE( LOG_SERVICE( "instance" )->Log\
					("%s q size = %u", name_.c_str(), q_.consumer_size() ) );	
			}
		}

		if(! q_.producer_size() )
			SLEEP( DEF_EMPTY_Q_SLEEP_TICK );		

		worker_->specificPerformed( work_obj_, 0 );
		
		lock_.Enter();
		q_.flip();
		lock_.Exit();		
	}

	LOG_INSTANCE( LOG_SERVICE( "instance" )->Log("db query thread end %s", __FILE__) );

	//return 0;
}
